FastAPI 请求全链路原理
从浏览器地址栏敲下回车,到页面显示结果,中间到底发生了什么。 这一篇讲原理;要查语法直接用 FastAPI 学习地图 的症状速查表;要系统学看讲义系列(从 01 HTTP 与 API 接口基础 开始)。
FastAPI 请求全链路原理
从浏览器地址栏敲下回车,到页面显示结果,中间到底发生了什么。 这一篇讲原理;要查语法直接用 FastAPI 学习地图 的症状速查表;要系统学看讲义系列(从 01 HTTP 与 API 接口基础 开始)。
一句话总览
浏览器访问:
http://127.0.0.1:8000/users/1完整过程大概是:
浏览器
↓
解析 URL
↓
DNS 查询 IP
↓
建立 TCP 连接
↓
发送 HTTP 请求
↓
服务器网卡收到数据
↓
操作系统交给端口对应的进程
↓
Uvicorn 接收请求
↓
转换成 ASGI 请求
↓
FastAPI 路由分发
↓
执行你的 Python 函数
↓
生成 HTTP 响应
↓
通过 TCP 发回浏览器
↓
浏览器解析响应并展示一、浏览器输入网址后发生了什么
假设你访问:
http://127.0.0.1:8000/items/100?name=book这个 URL 可以拆成:
| 部分 | 含义 |
|---|---|
http |
协议 |
127.0.0.1 |
服务器地址 |
8000 |
端口 |
/items/100 |
路径 |
?name=book |
查询参数 |
二、浏览器先确定“请求发给谁”
1. 如果是域名,需要 DNS 解析
比如:
https://www.example.com浏览器不知道 www.example.com 是哪台机器,所以要查 DNS:
www.example.com → 93.184.216.34DNS 的作用就是:
把域名翻译成 IP 地址。
如果是:
127.0.0.1
localhost就不用真正去公网查 DNS。
127.0.0.1 表示:
本机三、TCP 连接:浏览器和服务器建立通道
HTTP 请求不是直接“飞过去”的。
它通常跑在 TCP 连接上。
浏览器要先和服务器建立 TCP 连接:
浏览器: 我要连你
服务器: 可以连
浏览器: 好,开始通信这就是常说的 TCP 三次握手。
简化版:
浏览器 → 服务器:SYN
服务器 → 浏览器:SYN + ACK
浏览器 → 服务器:ACK建立完成后,双方之间就有一条可靠的数据通道。
四、端口是什么
IP 找到的是一台机器。
端口找到的是这台机器上的某个程序。
比如你的电脑上:
| 程序 | 端口 |
|---|---|
| FastAPI/Uvicorn | 8000 |
| MySQL | 3306 |
| PostgreSQL | 5432 |
| Redis | 6379 |
| SSH | 22 |
所以:
127.0.0.1:8000意思是:
本机上的 8000 端口对应的程序你启动 FastAPI 时:
uvicorn main:app --reloadUvicorn 默认监听:
127.0.0.1:8000也就是:
操作系统收到发往 8000 端口的数据后,交给 Uvicorn 进程。五、HTTP 请求长什么样
浏览器最终发出去的不是 Python 对象,而是一段文本格式的数据。
例如:
GET /items/100?name=book HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Chrome
Accept: application/json如果是 POST 请求,可能还会有请求体:
POST /users HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: application/json
{
"name": "Tom",
"age": 18
}HTTP 请求主要分成:
请求行
请求头
空行
请求体例如:
GET /items/100?name=book HTTP/1.1 ← 请求行
Host: 127.0.0.1:8000 ← 请求头
User-Agent: Chrome ← 请求头
← 空行
请求体 ← GET 一般没有请求体六、服务器机器收到请求后发生什么
请求到达服务器后,先不是 FastAPI 直接处理。
先经过:
网卡
↓
操作系统内核
↓
TCP/IP 协议栈
↓
找到端口 8000
↓
交给监听 8000 的进程也就是:
Uvicorn七、Uvicorn 是干什么的
FastAPI 本身不是直接监听端口的程序。
FastAPI 是一个 Web 框架。
真正负责监听端口、接收 TCP 数据、解析 HTTP 的是:
Uvicorn你可以理解成:
Uvicorn = 服务器门卫 + HTTP 接收员
FastAPI = 后台业务系统
你的函数 = 具体办事的人启动命令:
uvicorn main:app --reload含义是:
找到 main.py 里的 app 对象
用 Uvicorn 启动它
监听 HTTP 请求八、main:app 是什么意思
假设你有:
# main.py
from fastapi import FastAPI
app = FastAPI()命令:
uvicorn main:app --reload意思是:
main → main.py 文件
app → main.py 里的 app 变量
--reload → 代码改动后自动重启所以 Uvicorn 会加载:
from main import app九、ASGI 是什么
FastAPI 不是直接和 Uvicorn 乱连的。
它们之间有一个规范,叫:
ASGIASGI 可以理解成:
Python Web 服务器和 Python Web 框架之间的通信标准。
也就是规定:
Uvicorn 收到请求后,应该用什么格式交给 FastAPI。
FastAPI 处理完后,应该用什么格式把响应交还给 Uvicorn。所以整体关系是:
浏览器
↓ HTTP
Uvicorn
↓ ASGI
FastAPI
↓
你的路由函数十、FastAPI 内部怎么处理请求
假设代码是:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
def get_item(item_id: int, name: str):
return {
"item_id": item_id,
"name": name
}浏览器访问:
GET /items/100?name=bookFastAPI 会做这些事:
1. 接收 Uvicorn 传来的 ASGI 请求
2. 读取请求方法:GET
3. 读取请求路径:/items/100
4. 匹配路由:/items/{item_id}
5. 提取路径参数:item_id = "100"
6. 根据类型标注 int,把 "100" 转成 100
7. 读取查询参数:name = "book"
8. 调用你的函数:get_item(item_id=100, name="book")
9. 拿到返回值
10. 转成 JSON
11. 包装成 HTTP 响应
12. 交给 Uvicorn 发回浏览器十一、路由分发细节
你写的:
@app.get("/items/{item_id}")
def get_item(item_id: int):
return {"item_id": item_id}相当于告诉 FastAPI:
如果收到 GET /items/某个值
就调用 get_item()FastAPI 内部大概维护一张路由表:
| 请求方法 | 路径规则 | 函数 |
|---|---|---|
| GET | /items/{item_id} |
get_item |
| POST | /users |
create_user |
| GET | /users |
list_users |
收到请求后:
GET /items/100FastAPI 查表:
GET 匹配 GET
/items/100 匹配 /items/{item_id}
所以执行 get_item()这就是路由分发。
十二、参数从哪里来
FastAPI 会根据函数参数自动判断参数来源。
1. 路径参数
@app.get("/items/{item_id}")
def get_item(item_id: int):
return item_id请求:
GET /items/100来源:
item_id 来自 URL 路径2. 查询参数
@app.get("/items")
def get_items(page: int = 1, size: int = 10):
return {"page": page, "size": size}请求:
GET /items?page=2&size=20来源:
page=2
size=203. 请求体参数
from pydantic import BaseModel
class User(BaseModel):
name: str
age: int
@app.post("/users")
def create_user(user: User):
return user请求体:
{
"name": "Tom",
"age": 18
}FastAPI 会把 JSON 转成:
User(name="Tom", age=18)十三、FastAPI 为什么能自动校验类型
因为 FastAPI 读取了你的类型标注:
def get_item(item_id: int):它知道:
item_id 应该是 int如果请求:
GET /items/100可以转成整数:
item_id = 100如果请求:
GET /items/abc不能转成整数,FastAPI 自动返回:
{
"detail": [
{
"msg": "Input should be a valid integer"
}
]
}你的函数不会执行。
也就是说:
请求参数不合法
↓
FastAPI 直接拦截
↓
返回 422 错误十四、你的函数执行完以后发生什么
比如:
@app.get("/items/{item_id}")
def get_item(item_id: int):
return {
"item_id": item_id,
"name": "book"
}返回的是 Python 字典:
{
"item_id": 100,
"name": "book"
}但是浏览器不能直接接收 Python 字典。
FastAPI 会把它转成 JSON:
{
"item_id": 100,
"name": "book"
}然后包装成 HTTP 响应:
HTTP/1.1 200 OK
content-type: application/json
{
"item_id": 100,
"name": "book"
}十五、HTTP 响应长什么样
HTTP 响应也分几部分:
状态行
响应头
空行
响应体例如:
HTTP/1.1 200 OK
content-type: application/json
content-length: 29
{"item_id":100,"name":"book"}状态码常见有:
| 状态码 | 含义 |
|---|---|
| 200 | 成功 |
| 201 | 创建成功 |
| 400 | 请求有问题 |
| 401 | 未登录 |
| 403 | 没权限 |
| 404 | 路由不存在 |
| 422 | 参数校验失败 |
| 500 | 服务器内部错误 |
十六、响应怎么回到浏览器
响应返回路线基本反过来:
你的函数
↓
FastAPI 转 JSON
↓
Uvicorn 转 HTTP 响应
↓
操作系统 TCP 发送
↓
网络传输
↓
浏览器接收
↓
浏览器解析响应如果响应头是:
content-type: application/json浏览器知道这是 JSON。
如果是:
content-type: text/html浏览器就按 HTML 页面渲染。
十七、完整流程图
用户访问 URL
↓
浏览器解析 URL
↓
DNS:域名 → IP
↓
TCP 三次握手,建立连接
↓
浏览器构造 HTTP 请求
↓
请求通过网络到服务器
↓
服务器操作系统收到数据
↓
根据端口交给 Uvicorn
↓
Uvicorn 解析 HTTP
↓
Uvicorn 按 ASGI 标准交给 FastAPI
↓
FastAPI 查路由表
↓
提取路径参数 / 查询参数 / 请求体
↓
Pydantic 做类型转换和数据校验
↓
执行你的路径操作函数
↓
函数返回 Python 对象
↓
FastAPI 转成 JSON 响应
↓
Uvicorn 发回 HTTP 响应
↓
浏览器收到响应
↓
浏览器展示结果十八、用一段 FastAPI 代码串起来
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class User(BaseModel):
name: str
age: int
@app.post("/users/{user_id}")
def update_user(user_id: int, user: User, token: str):
return {
"user_id": user_id,
"name": user.name,
"age": user.age,
"token": token
}请求:
POST /users/10?token=abc123 HTTP/1.1
Host: 127.0.0.1:8000
Content-Type: application/json
{
"name": "Tom",
"age": 18
}FastAPI 判断:
| 参数 | 来源 |
|---|---|
user_id |
路径 /users/10 |
token |
查询参数 ?token=abc123 |
user |
JSON 请求体 |
最终调用:
update_user(
user_id=10,
token="abc123",
user=User(name="Tom", age=18)
)返回:
{
"user_id": 10,
"name": "Tom",
"age": 18,
"token": "abc123"
}十九、再压缩成一句核心理解
FastAPI 的完整请求处理可以记成:
浏览器发 HTTP 请求
→ Uvicorn 接收
→ ASGI 转交
→ FastAPI 路由分发
→ 参数解析和校验
→ 执行你的函数
→ 返回 JSON
→ Uvicorn 发回浏览器最关键的是分清三层:
| 层 | 负责什么 |
|---|---|
| Uvicorn | 监听端口,接收 HTTP |
| ASGI | Uvicorn 和 FastAPI 之间的通信规范 |
| FastAPI | 路由分发、参数校验、执行函数、生成响应 |
相关:FastAPI 学习地图 · 01 HTTP 与 API 接口基础 · 从项目学 FastAPI 全景笔记